﻿using System;
using System.Management;
using System.Security.Cryptography;
using System.Text;

namespace T2ReportsAssistant
{
    public class CryptoService
    {
        private static CryptoAPITransform _encryptor;
        private static CryptoAPITransform _decryptor;

        internal string GetKeyString()
        {
            ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_BaseBoard");

            foreach (ManagementObject wmi in searcher.Get())
            {
                try
                {
                    return wmi.GetPropertyValue("SerialNumber").ToString();
                }
                catch { }
            }
            return Environment.UserName;
        }

        private CryptoService()
        {
            TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

            byte[] iv = new byte[8] { 0xFF, 0x78, 0x4B, 0xCF, 0x98, 0xDE, 0x46, 0x56 };
            byte[] key = md5.ComputeHash(Encoding.ASCII.GetBytes(GetKeyString()));

            _encryptor = (CryptoAPITransform)tripleDES.CreateEncryptor(key, iv);
            _decryptor = (CryptoAPITransform)tripleDES.CreateDecryptor(key, iv);
        }

        #region Singletone Pattern Code

        private static CryptoService _instance;
        private static readonly object _padLock = new object();

        public static CryptoService Instance
        {
            get
            {
                lock (_padLock)
                {
                    if (_instance == null)
                    {
                        _instance = new CryptoService();
                    }

                    return _instance;
                }
            }
        }
        #endregion

        /// <summary>
        /// Encrypts the specified string.
        /// </summary>
        /// <param name="str">The string to be encrypted.</param>
        /// <returns>The encrypted string.</returns>
        public string Encrypt(string str)
        {
            byte[] buffer = Encoding.ASCII.GetBytes(str);

            return Convert.ToBase64String(_encryptor.TransformFinalBlock(buffer, 0, buffer.Length));
        }

        /// <summary>
        /// Decrypts the supplied string string.
        /// </summary>
        /// <param name="str">The string.</param>
        /// <returns></returns>
        public string Decrypt(string str)
        {
            byte[] buffer;
            try
            {
                buffer = Convert.FromBase64String(str);
            }
            catch
            {
                buffer = new byte[1] { 0x20 };
            }

            return Encoding.ASCII.GetString(_decryptor.TransformFinalBlock(buffer, 0, buffer.Length));
        }
    }
}
